home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
comm
/
term
/
term34Source.lha
/
termGadTools.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-16
|
78KB
|
3,731 lines
/*
** termGadTools.c
**
** GadTools object management support routines
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#ifdef DEBUG
#include "termDebug.h"
#endif /* DEBUG */
/* Some includes for starters. */
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <intuition/sghooks.h>
#include <utility/tagitem.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <clib/intuition_protos.h>
/*#include <clib/gadtools_protos.h>*/
#include <clib/diskfont_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/exec_protos.h>
#include <string.h>
#include <stdarg.h>
/* Some useful minterms. */
#define MINTERM_COPY ABC | ABNC | NABC | NABNC
#define MINTERM_NOT_C ABNC | ANBNC | NABNC | NANBNC
#define MINTERM_NOT_B_AND_C ANBC | NANBC
#define MINTERM_B_OR_C ABC | ABNC | NABC | NABNC | ANBC | NANBC
/* User interface definitions. */
#define SZLV_Display 1 /* Listview includes display */
#define SZLV_String 2 /* Listview includes string */
#define FOLDER_KIND 42 /* Folder selection button. */
#define FILE_KIND 43 /* File selection button. */
#define PASSWORD_KIND 44 /* Password entry string gadget. */
#define SCREEN_KIND 45 /* Screen selection button. */
#define SZ_Adjust TAG_USER+1 /* Adjust object */
#define SZ_AutoWidth TAG_USER+2 /* Use default width? */
#define SZ_AlignExtra TAG_USER+3 /* Add extra space to top edge */
#define SZ_NewColumn TAG_USER+4 /* Start new column */
#define SZ_Lines TAG_USER+5 /* Number of lines in object */
#define SZ_Chars TAG_USER+6 /* Number of chars (width) in object */
#define SZ_AlignLeft TAG_USER+7 /* Align to left border */
#define SZ_AlignRight TAG_USER+8 /* Align to right border */
#define SZ_AlignCentre TAG_USER+9 /* Centre it */
#define SZ_AlignBottom TAG_USER+10 /* Align to window bottom */
#define SZ_GroupCount TAG_USER+11 /* Create a group with N objects */
#define SZ_GroupNext TAG_USER+12 /* Skip to next position */
#define SZ_SaveX TAG_USER+13 /* Place left to current object, don't touch the left edge position, though. */
#define SZ_SaveY TAG_USER+14 /* Place below current object, don't touch the top edge position, though. */
#define SZ_UseLeft TAG_USER+15 /* Use this coordinate as left edge. */
#define SZ_UseTop TAG_USER+16 /* Use this coordinate as top edge. */
#define SZ_UseWidth TAG_USER+17 /* Use this gadget width. */
#define SZ_UseHeight TAG_USER+18 /* Use this gadget height. */
#define SZ_FullWidth TAG_USER+19 /* Use full window width for gadget. */
#define SZ_FullHeight TAG_USER+20 /* Use full window height for gadget. */
#define SZ_SmallSpace TAG_USER+21 /* Provide small alignment space. */
#define SZ_LeaveFolder TAG_USER+22 /* Leave space for folder icon. */
#define SZ_PlaceLeft TAG_USER+23 /* Place left to current object, don't modify next object position. */
#define SZ_PlaceBelow TAG_USER+24 /* Place below current object, don't modify next object position. */
#define SZ_InterHeight TAG_USER+25 /* Use this inter-object space. */
/* Box information types. */
enum { BOX_LEFT,BOX_TOP,BOX_WIDTH,BOX_HEIGHT };
/* Use these macros if the corresponding functions are not available. */
extern ULONG (* __regargs ReadAPen)(struct RastPort *RPort);
extern ULONG (* __regargs ReadBPen)(struct RastPort *RPort);
extern ULONG (* __regargs ReadDrMd)(struct RastPort *RPort);
/* Image types */
enum { BUTTONIMAGE_FOLDER, BUTTONIMAGE_FILE, BUTTONIMAGE_SCREEN };
/* External data. */
extern struct Library *GadToolsBase,
*DiskfontBase;
extern struct Gadget *ActiveGadget;
extern UBYTE SharedBuffer[];
extern struct TextAttr UserFont;
extern APTR VisualInfo;
extern LONG InterWidth,
InterHeight;
extern struct Hook CommandHook,
PasswordHook;
extern struct TextFont *UserTextFont;
/* This structure will help us to remember the current state of
* a GadTools object.
*/
struct GadgetSupportInfo
{
STRPTR Original, /* Password string entry, original contents (for undo). */
Buffer; /* Password string entry, current contents. */
struct GadgetSupportInfo *PointBack; /* Points back to itself. */
struct Gadget *Gadget; /* Points back to the host. */
struct Image *Image; /* Folder images. */
STRPTR Title; /* New gadget title. */
WORD Kind; /* Item type (BUTTON_KIND, STRING_KIND, etc.) */
UBYTE Key; /* The key to press. */
BYTE ReadOnly; /* LISTVIEW_KIND only: is this a read-only object? */
LONG Current, /* Current state or counter. */
Min, /* Minimum value for `Current'. */
Max; /* Maximum value for `Current'. */
UWORD Flags; /* Miscellaneous flag values. */
};
/* A text box for several lines of text. */
struct TextBox
{
struct TextBox *NextBox; /* Next box in chain. */
LONG Left,Top, /* Position and size. */
Width,Height;
LONG LineWidth, /* Line width in pixels. */
LineHeight; /* Line height in pixels. */
LONG NumChars, /* Number of chars per line. */
NumLines; /* Number of lines. */
STRPTR *Title, /* Line titles. */
*Text; /* Line texts. */
LONG TitleFgPen,
TitleBgPen,
TextPen;
};
/* Our home-made tag items. */
STATIC Tag PrivateTags[] =
{
SZ_Adjust,
SZ_AutoWidth,
SZ_AlignExtra,
SZ_NewColumn,
SZ_Lines,
SZ_Chars,
SZ_AlignLeft,
SZ_AlignRight,
SZ_AlignCentre,
SZ_AlignBottom,
SZ_GroupCount,
SZ_GroupNext,
SZ_SaveX,
SZ_SaveY,
SZ_UseLeft,
SZ_UseTop,
SZ_UseWidth,
SZ_UseHeight,
SZ_FullWidth,
SZ_FullHeight,
SZ_SmallSpace,
SZ_LeaveFolder,
SZ_PlaceLeft,
SZ_PlaceBelow,
SZ_InterHeight,
TAG_DONE
};
/* Sizing data. */
STATIC struct RastPort *SZ_RPort;
STATIC struct TextFont *SZ_TextFont;
STATIC struct Screen *SZ_Screen;
STATIC LONG SZ_Left,
SZ_Top,
SZ_WindowWidth,
SZ_WindowHeight;
SZ_CurrentLeft,
SZ_CurrentTop,
SZ_CurrentWidth,
SZ_MaxWidth,
SZ_GroupDelta,
SZ_GroupX,
SZ_WidthMax,
SZ_TextPen,
SZ_LastLeft,
SZ_LastTop,
SZ_LastWidth,
SZ_LastHeight;
/* Dimensions of the font glyphs. */
STATIC ULONG SZ_AverageGlyphWidth, /* Average width. */
SZ_MaxGlyphWidth, /* Maximum width. */
SZ_MaxNumericWidth; /* Maximum numeral width. */
/* AmigaGuide help. */
extern VOID GuideSetup(VOID);
/* Local routines. */
struct Gadget * CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...);
VOID FreeGadgets(struct Gadget *GadgetList);
VOID GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...);
VOID GT_ReplyIMsg(struct IntuiMessage *Message);
VOID KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code);
/* Sizing routines. */
LONG SZ_GetWindowWidth(VOID);
LONG SZ_GetWindowHeight(VOID);
LONG SZ_GetLeftEdge(VOID);
LONG SZ_GetTopEdge(VOID);
VOID __regargs SZ_SetTopEdge(LONG Top);
VOID __regargs SZ_SetLeftEdge(LONG Left);
VOID __regargs SZ_SetAbsoluteTop(LONG Top);
VOID __regargs SZ_SetAbsoluteLeft(LONG Left);
VOID __regargs SZ_SetWidth(LONG Width);
VOID SZ_InitWidth(VOID);
LONG SZ_ResetMaxWidth(VOID);
VOID __regargs SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
VOID __regargs SZ_GetDimension(LONG *Width,LONG *Height);
LONG __regargs SZ_TextWidth(STRPTR String);
VOID __regargs SZ_AddLeftOffset(LONG Offset);
LONG __stdargs SZ_LeftOffsetN(LONG DataArray,...);
LONG __regargs SZ_LeftOffsetDelta(LONG From,LONG To);
VOID SZ_SizeCleanup(VOID);
BYTE __regargs SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title);
ULONG __regargs SZ_GetNumericLen(STRPTR String);
ULONG __regargs SZ_GetGlyphLen(STRPTR String);
ULONG __regargs SZ_GetLen(STRPTR String);
LONG __regargs SZ_Height(UBYTE Type,LONG Lines,BYTE Display);
LONG __regargs SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
/* Text box routines. */
VOID __regargs SZ_FreeBox(struct TextBox *Box);
VOID __regargs SZ_FreeBoxes(struct TextBox *FirstBox);
LONG __regargs SZ_BoxWidth(LONG Chars);
LONG __regargs SZ_BoxHeight(LONG Lines);
VOID __regargs SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen);
struct TextBox * __stdargs SZ_CreateTextBox(struct TextBox **FirstBox,...);
VOID __stdargs SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...);
VOID __regargs SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String);
VOID __stdargs SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...);
VOID __regargs SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box);
VOID __regargs SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox);
VOID __regargs SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top);
VOID __regargs SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
VOID __regargs SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top);
VOID __regargs SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
LONG __regargs SZ_GetBoxInfo(struct TextBox *Box,LONG Type);
/* The original gadtools.library routines. */
struct Gadget * OldCreateGadgetA(ULONG,struct Gadget *,struct NewGadget *,struct TagItem *);
VOID OldFreeGadgets(struct Gadget *);
VOID OldGT_SetGadgetAttrsA(struct Gadget *,struct Window *,struct Requester *,struct TagItem *);
VOID OldGT_ReplyIMsg(struct IntuiMessage *);
VOID DrawBevelBox(struct RastPort *,LONG,LONG,LONG,LONG,...);
/* Pragma calls: the easy way. */
#pragma libcall GadToolsBase OldCreateGadgetA 1E A98004
#pragma libcall GadToolsBase OldFreeGadgets 24 801
#pragma libcall GadToolsBase OldGT_SetGadgetAttrsA 2A BA9804
#pragma libcall GadToolsBase OldGT_ReplyIMsg 4E 901
/* CreateButtonImages():
*
* Create images for the folder and file buttons.
*/
STATIC struct Image *
CreateButtonImages(BYTE Type,UWORD Width,UWORD Height,struct Screen *Screen,APTR VisualInfo)
{
struct Image *Image = NULL;
/* Minimum size required. */
if(Width >= 16 && Height >= 12)
{
struct RastPort *RPort;
/* Allocate local dummy rastport. */
if(RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
{
struct BitMap *BitMap[2] = { NULL, NULL };
BYTE Success;
WORD Depth,
i,j;
/* Determine screen depth. */
Depth = Screen -> RastPort . BitMap -> Depth;
/* Set up rastport. */
InitRastPort(RPort);
/* Allocate bitmaps and bitplane data. */
Success = TRUE;
for(i = 0 ; Success && i < 2 ; i++)
{
if(BitMap[i] = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
{
InitBitMap(BitMap[i],Depth,Width,Height);
if(BitMap[i] -> Planes[0] = (PLANEPTR)AllocVec(BitMap[i] -> BytesPerRow * BitMap[i] -> Rows * BitMap[i] -> Depth,MEMF_CHIP | MEMF_CLEAR))
{
for(j = 1 ; j < Depth ; j++)
BitMap[i] -> Planes[j] = BitMap[i] -> Planes[j - 1] + BitMap[i] -> BytesPerRow * BitMap[i] -> Rows;
}
else
Success = FALSE;
}
else
Success = FALSE;
}
/* Did we get what we wanted? */
if(Success)
{
struct DrawInfo *DrawInfo;
/* Get drawing pen information. */
if(DrawInfo = GetScreenDrawInfo(Screen))
{
/* Run-dump of the folder image. */
STATIC UWORD __chip FolderData[10] =
{
0x03C0,
0x0420,
0xF810,
0xFC10,
0xC3F0,
0xC010,
0xC010,
0xC010,
0xC010,
0xFFF0
};
/* Run-dump of the file image. */
STATIC UWORD __chip FileData[10] =
{
0xFF00,
0x8180,
0x8140,
0x8120,
0x81F0,
0x8010,
0x8010,
0x8010,
0x8010,
0xFFF0
};
/* Run-dump of the screen image. */
STATIC UWORD __chip ScreenData[10] =
{
0xFFF0,
0x8050,
0xFFF0,
0x8010,
0x8010,
0x8010,
0x8010,
0x8010,
0x8010,
0xFFF0
};
struct BitMap __aligned FolderBitMap;
WORD Left,
Top;
/* Determine image offsets. */
Left = (Width - 12) / 2;
Top = (Height - 10) / 2;
/* Set up the folder bitmap. */
InitBitMap(&FolderBitMap,Depth,12,10);
/* Put the mask into all bitplanes. */
switch(Type)
{
case BUTTONIMAGE_FOLDER:
for(i = 0 ; i < Depth ; i++)
FolderBitMap . Planes[i] = (PLANEPTR)FolderData;
break;
case BUTTONIMAGE_FILE:
for(i = 0 ; i < Depth ; i++)
FolderBitMap . Planes[i] = (PLANEPTR)FileData;
break;
case BUTTONIMAGE_SCREEN:
for(i = 0 ; i < Depth ; i++)
FolderBitMap . Planes[i] = (PLANEPTR)ScreenData;
break;
}
/* Manipulate the first bitmap. */
RPort -> BitMap = BitMap[0];
/* Clear the bitmap. */
SetRast(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
/* Draw the button box. */
DrawBevelBox(RPort,0,0,Width,Height,
GT_VisualInfo, VisualInfo,
TAG_DONE);
/* Clear the folder mask. */
BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,MINTERM_NOT_B_AND_C,(1 << Depth) - 1,NULL);
/* Draw the folder mask. */
BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,MINTERM_B_OR_C,DrawInfo -> dri_Pens[TEXTPEN],NULL);
/* Are we to provide a selecte
* image in the new look?
*/
if((DrawInfo -> dri_Flags & DRIF_NEWLOOK) && Depth > 1)
{
/* Manipulate the second bitmap. */
RPort -> BitMap = BitMap[1];
/* Set the bitmap to the
* selected button colour.
*/
SetRast(RPort,DrawInfo -> dri_Pens[FILLPEN]);
/* Draw the selected button box. */
DrawBevelBox(RPort,0,0,Width,Height,
GTBB_Recessed, TRUE,
GT_VisualInfo, VisualInfo,
TAG_DONE);
/* Clear the folder mask. */
BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,MINTERM_NOT_B_AND_C,(1 << Depth) - 1,NULL);
/* Draw the folder mask. */
BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,MINTERM_B_OR_C,DrawInfo -> dri_Pens[FILLTEXTPEN],NULL);
}
else
{
/* Copy the image. */
BltBitMap(BitMap[0],0,0,BitMap[1],0,0,Width,Height,MINTERM_COPY,(1 << Depth) - 1,NULL);
/* Invert the inner area. */
BltBitMap(BitMap[0],0,0,BitMap[1],2,1,Width - 4,Height - 2,MINTERM_NOT_C,(1 << Depth) - 1,NULL);
}
/* Allocate space for standard image and selected image. */
if(Image = (struct Image *)AllocVec(2 * sizeof(struct Image),MEMF_ANY | MEMF_CLEAR))
{
/* Fill in the standard data. */
for(i = 0 ; i < 2 ; i++)
{
Image[i] . Width = Width;
Image[i] . Height = Height;
Image[i] . Depth = Depth;
Image[i] . ImageData = (UWORD *)BitMap[i] -> Planes[0];
Image[i] . PlanePick = (1 << Depth) - 1;
}
}
/* Free the screen drawing pen information. */
FreeScreenDrawInfo(Screen,DrawInfo);
}
}
/* Free the bitmaps, but not necessarily the
* bitplane data.
*/
for(i = 0 ; i < 2 ; i++)
{
if(BitMap[i])
{
if(!Success)
FreeVec(BitMap[i] -> Planes[0]);
FreeVec(BitMap[i]);
}
}
/* Free the rastport. */
FreeVec(RPort);
}
}
/* Return the result. */
return(Image);
}
/* NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create):
*
* Prepare a new slider title, padding the label with spaces.
*/
STATIC STRPTR __regargs
NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create)
{
register LONG i,TotalLen,NumSpaces = 0,Last;
/* Determine length of title text. */
TotalLen = Last = strlen(Original);
/* Count the trailing spaces, look for the
* last character which is not a space.
*/
for(i = TotalLen - 1 ; i >= 0 ; i--)
{
/* Is this a space? */
if(Original[i] == ' ')
{
/* Increment number of spaces. */
NumSpaces++;
/* Remember last space position. */
Last = i;
}
else
break;
}
/* No spaces? Return the defaults. */
if(!Len && !NumSpaces)
{
/* Reset the information. */
if(MaxPixelLen)
*MaxPixelLen = 0;
/* Return original buffer. */
return(Original);
}
else
{
/* If no length is given, use the
* values we have determined. */
if(!Len)
Len = NumSpaces + 1;
/* if(MaxPixelLen)
*MaxPixelLen = Len * SZ_MaxNumericWidth;*/
NumSpaces = ((Len - 1) * SZ_MaxNumericWidth) / TextLength(SZ_RPort," ",1) + 1;
/* Copy the body. */
memcpy(SharedBuffer,Original,Last);
/* Supply the spaces if any. */
if(NumSpaces)
memset(SharedBuffer + Last,' ',NumSpaces);
/* Provide null-termination. */
SharedBuffer[Last + NumSpaces] = 0;
/* Are we to allocate a buffer to
* hold the new label?
*/
if(Create)
{
STRPTR Buffer;
/* Allocate and copy the buffer. */
if(Buffer = (STRPTR)AllocVec(Last + NumSpaces + 1,MEMF_ANY))
strcpy(Buffer,SharedBuffer);
/* Return the result. */
return(Buffer);
}
else
return(SharedBuffer);
}
}
/* CreateGadget():
*
* A frontend to the original routine.
*/
struct Gadget *
CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...)
{
STATIC struct NewGadget Backup;
va_list VarArgs;
struct TagItem *TagList,
*ThisTag,
MoreTags[3];
struct GadgetSupportInfo *Info = NULL;
WORD i;
struct Gadget *Result;
UWORD Flags = NULL;
STRPTR NewGadgetTitle = NULL;
LONG MaxPixelLen = 0;
/* Get the tag item array. */
va_start(VarArgs,New);
/* Make a backup copy of the original NewGadget structure,
* we may want to modify it.
*/
CopyMem(New,&Backup,sizeof(struct NewGadget));
New = &Backup;
/* Fill in the defaults if none are present. */
if(!New -> ng_VisualInfo)
New -> ng_VisualInfo = VisualInfo;
if(!New -> ng_TextAttr)
New -> ng_TextAttr = &UserFont;
/* Get the tag item list. */
TagList = (struct TagItem *)VarArgs;
/* Is this a slider object? */
if(Kind == SLIDER_KIND && New -> ng_GadgetText)
{
/* Is a special label width required? */
if(ThisTag = FindTagItem(GTSL_MaxLevelLen,TagList))
NewGadgetTitle = NewTitle(New -> ng_GadgetText,ThisTag -> ti_Data + 1,&MaxPixelLen,TRUE);
else
NewGadgetTitle = NewTitle(New -> ng_GadgetText,0,&MaxPixelLen,TRUE);
}
/* Try to find the SZ_Adjust tag item. If found, we are to
* apply our formatting functions to it.
*/
if(ThisTag = FindTagItem(SZ_Adjust,TagList))
{
if(ThisTag -> ti_Data)
{
LONG Width,
Height,
AddHeight = InterHeight,
Left = SZ_CurrentLeft,
Top = SZ_CurrentTop;
BYTE AutoWidth = FALSE,
MoveDown = TRUE,
SaveWidth = TRUE,
SetLeft = FALSE,
SetBelow = FALSE,
DropLeft = FALSE,
DropTop = FALSE;
/* Are we to leave the left edge untouched? */
if(ThisTag = FindTagItem(SZ_SaveX,TagList))
SetLeft = ThisTag -> ti_Data;
/* Are we to leave the top edge untouched? */
if(ThisTag = FindTagItem(SZ_SaveY,TagList))
SetBelow = ThisTag -> ti_Data;
/* Are we to use a special inter-object alignment size? */
if(ThisTag = FindTagItem(SZ_InterHeight,TagList))
AddHeight = ThisTag -> ti_Data;
/* Are we to place the new object to the left
* of the previous object?
*/
if(ThisTag = FindTagItem(SZ_PlaceLeft,TagList))
{
if(ThisTag -> ti_Data)
{
Top = SZ_LastTop;
Left = SZ_LastLeft + SZ_LastWidth + 2;
DropLeft = TRUE;
DropTop = TRUE;
}
}
/* Are we to place the new object below
* the previous object?
*/
if(ThisTag = FindTagItem(SZ_PlaceBelow,TagList))
{
if(ThisTag -> ti_Data)
{
Top = SZ_LastTop + SZ_LastHeight + 1;
DropLeft = TRUE;
}
}
/* Are we to align the object to the
* window bottom?
*/
if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
{
if(ThisTag -> ti_Data)
Top = SZ_WindowHeight;
}
/* Are we to add extra space to the
* object top edge?
*/
if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
{
if(ThisTag -> ti_Data)
Top += AddHeight;
}
/* Are we to start a new column? */
if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
{
if(ThisTag -> ti_Data)
{
Top = SZ_Top;
Left = Left + SZ_MaxWidth;
SZ_MaxWidth = 0;
if(ThisTag = FindTagItem(SZ_SmallSpace,TagList))
{
if(ThisTag -> ti_Data)
Left += 2;
else
Left += InterWidth;
}
else
Left += InterWidth;
}
}
/* Is the object to contain a certain
* number of lines?
*/
if(ThisTag = FindTagItem(SZ_Lines,TagList))
{
LONG Lines = (LONG)ThisTag -> ti_Data;
/* Is it a listview object? */
if(Kind == LISTVIEW_KIND)
{
/* Determine height of object. */
if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
{
if(ThisTag -> ti_Data)
Height = SZ_Height(Kind,Lines,SZLV_String);
else
Height = SZ_Height(Kind,Lines,SZLV_Display);
}
else
Height = SZ_Height(Kind,Lines,NULL);
}
else
Height = SZ_Height(Kind,Lines,NULL);
}
else
{
/* If this is a MX kind object,
* determine the number of lines
* by looking at the labels.
*/
if(ThisTag = FindTagItem(GTMX_Labels,TagList))
{
STRPTR *Choices;
LONG Lines = 0;
Choices = (STRPTR *)ThisTag -> ti_Data;
while(*Choices++)
Lines++;
Height = SZ_Height(Kind,Lines,NULL);
}
else
Height = SZ_Height(Kind,0,NULL);
}
/* Is the object width derived from
* certain magical calculations or
* is it as wide as the default width?
*/
if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
AutoWidth = ThisTag -> ti_Data;
/* Determine the width of the object. */
if(!AutoWidth)
{
STRPTR *Choices = NULL,
Title = NULL;
LONG Chars = 0;
/* Determine number of characters in
* this object.
*/
if(ThisTag = FindTagItem(SZ_Chars,TagList))
Chars = ThisTag -> ti_Data;
/* If this is a button object,
* calculate the width by looking
* at the title.
*/
if(Kind == BUTTON_KIND && New -> ng_GadgetText)
Title = New -> ng_GadgetText;
/* If this is a cycle object,
* take a look at the labels.
*/
if(ThisTag = FindTagItem(GTCY_Labels,TagList))
Choices = (STRPTR *)ThisTag -> ti_Data;
/* If this is a listview object,
* take a look at the list.
*/
if(ThisTag = FindTagItem(GTLV_Labels,TagList))
{
if(ThisTag -> ti_Data != ~0)
{
struct List *List = (struct List *)ThisTag -> ti_Data;
struct Node *Node;
LONG Len;
Node = List -> lh_Head;
while(Node -> ln_Succ)
{
if((Len = strlen(Node -> ln_Name)) > Chars)
Chars = Len;
Node = Node -> ln_Succ;
}
}
}
/* Determine object width. */
Width = SZ_Width(Kind,Title,Chars,Choices);
}
else
{
/* Use the default width. */
Width = SZ_CurrentWidth;
/* A checkbox object has a
* fixed width. We don't want
* any other objects to share
* it.
*/
if(Kind == CHECKBOX_KIND || Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND)
{
Width = SZ_Width(Kind,NULL,0,NULL);
SaveWidth = FALSE;
}
}
/* Are we to align this object to
* the left window edge?
*/
if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
{
if(ThisTag -> ti_Data)
{
Left = SZ_Left;
MoveDown = FALSE;
}
}
/* Are we to use a specific object width? */
if(ThisTag = FindTagItem(SZ_UseWidth,TagList))
Width = ThisTag -> ti_Data;
/* Are we to use a specific object height? */
if(ThisTag = FindTagItem(SZ_UseHeight,TagList))
Height = ThisTag -> ti_Data;
/* Are we to align this object to the
* right window edge?
*/
if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
{
if(ThisTag -> ti_Data)
{
Left = SZ_WindowWidth - INTERWIDTH - Width;
MoveDown = FALSE;
}
}
/* Are we to centre the object in
* the window?
*/
if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
{
if(ThisTag -> ti_Data)
{
Left = (SZ_WindowWidth - Width) / 2;
MoveDown = FALSE;
}
}
/* Are we to build a horizontal group
* using the following objects?
*/
if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
{
LONG Count = ThisTag -> ti_Data,
Width = SZ_WindowWidth;
if(!Width)
Width = SZ_WindowWidth = SZ_Left + Count * (SZ_CurrentWidth + 2) + InterWidth;
if(!Top)
Top = SZ_Top;
/* Use a specific left edge? */
if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
{
Width -= ThisTag -> ti_Data - InterWidth;
SZ_GroupDelta = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
SZ_GroupX = Left = ThisTag -> ti_Data;
}
else
{
SZ_GroupDelta = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
SZ_GroupX = Left = SZ_Left;
}
MoveDown = FALSE;
}
else
{
if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
Left = ThisTag -> ti_Data;
}
/* Skip to the next group item position? */
if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
{
if(ThisTag -> ti_Data)
{
SZ_GroupX += SZ_GroupDelta;
Left = SZ_GroupX;
MoveDown = FALSE;
}
}
/* Determine default label placement. */
switch(Kind)
{
case MX_KIND:
New -> ng_Flags = (New -> ng_Flags & ~(PLACETEXT_LEFT|PLACETEXT_RIGHT|PLACETEXT_ABOVE|PLACETEXT_BELOW|PLACETEXT_IN)) | PLACETEXT_LEFT;
SaveWidth = FALSE;
break;
case CHECKBOX_KIND:
SaveWidth = FALSE;
break;
default:
if(New -> ng_Flags & PLACETEXT_ABOVE)
Top += INTERHEIGHT + SZ_TextFont -> tf_YSize;
break;
}
/* Use a specific top edge? */
if(ThisTag = FindTagItem(SZ_UseTop,TagList))
Top = ThisTag -> ti_Data;
/* Gadget is to be as wide as the entire window? */
if(ThisTag = FindTagItem(SZ_FullWidth,TagList))
{
if(ThisTag -> ti_Data)
Width = SZ_WindowWidth - (InterWidth + Left);
}
/* Gadget is to be as high as the entire window? */
if(ThisTag = FindTagItem(SZ_FullHeight,TagList))
{
if(ThisTag -> ti_Data)
Height = SZ_WindowHeight - (AddHeight + SZ_Top + Top);
}
/* Leave space for folder icon? */
if(ThisTag = FindTagItem(SZ_LeaveFolder,TagList))
{
if(ThisTag -> ti_Data && (Kind == STRING_KIND || Kind == PASSWORD_KIND))
New -> ng_Width = Width - (2 + SZ_Width(FOLDER_KIND,"",0,0));
else
New -> ng_Width = Width;
}
else
New -> ng_Width = Width;
/* Fill in the NewGadget. */
New -> ng_LeftEdge = Left;
New -> ng_TopEdge = Top;
New -> ng_Height = Height;
/* Add the default tags. */
switch(Kind)
{
/* case SLIDER_KIND:
MoreTags[0] . ti_Tag = GTSL_MaxPixelLen;
MoreTags[0] . ti_Data = MaxPixelLen;
MoreTags[1] . ti_Tag = GTSL_Justification;
MoreTags[1] . ti_Data = GTJ_RIGHT;
MoreTags[2] . ti_Tag = TAG_MORE;
MoreTags[2] . ti_Data = (ULONG)TagList;
if(MaxPixelLen)
TagList = MoreTags;
else
TagList = MoreTags + 1;
break;*/
case PALETTE_KIND:
MoreTags[0] . ti_Tag = GTPA_IndicatorWidth;
MoreTags[0] . ti_Data = Width / 4;
MoreTags[1] . ti_Tag = GTPA_IndicatorHeight;
MoreTags[1] . ti_Data = Height;
MoreTags[2] . ti_Tag = TAG_MORE;
MoreTags[2] . ti_Data = (ULONG)TagList;
TagList = MoreTags;
break;
case LISTVIEW_KIND:
MoreTags[0] . ti_Tag = GTLV_ScrollWidth;
MoreTags[0] . ti_Data = 2 + 2 * SZ_AverageGlyphWidth + 2;
MoreTags[1] . ti_Tag = TAG_MORE;
MoreTags[1] . ti_Data = (ULONG)TagList;
TagList = MoreTags;
break;
case CHECKBOX_KIND:
MoreTags[0] . ti_Tag = GTCB_Scaled;
MoreTags[0] . ti_Data = TRUE;
MoreTags[1] . ti_Tag = TAG_MORE;
MoreTags[1] . ti_Data = (ULONG)TagList;
TagList = MoreTags;
break;
case MX_KIND:
MoreTags[0] . ti_Tag = GTMX_Scaled;
MoreTags[0] . ti_Data = TRUE;
MoreTags[1] . ti_Tag = TAG_MORE;
MoreTags[1] . ti_Data = (ULONG)TagList;
TagList = MoreTags;
break;
case STRING_KIND:
MoreTags[0] . ti_Tag = GTST_EditHook;
MoreTags[0] . ti_Data = (ULONG)&CommandHook;
MoreTags[1] . ti_Tag = GA_Immediate;
MoreTags[1] . ti_Data = TRUE;
MoreTags[2] . ti_Tag = TAG_MORE;
MoreTags[2] . ti_Data = (ULONG)TagList;
if(!FindTagItem(GTST_EditHook,TagList))
TagList = MoreTags;
else
TagList = MoreTags + 1;
break;
case PASSWORD_KIND:
MoreTags[0] . ti_Tag = GTST_EditHook;
MoreTags[0] . ti_Data = (ULONG)&PasswordHook;
MoreTags[1] . ti_Tag = GA_Immediate;
MoreTags[1] . ti_Data = TRUE;
MoreTags[2] . ti_Tag = TAG_MORE;
MoreTags[2] . ti_Data = (ULONG)TagList;
TagList = MoreTags;
break;
case INTEGER_KIND:
MoreTags[0] . ti_Tag = GTIN_EditHook;
MoreTags[0] . ti_Data = (ULONG)&CommandHook;
MoreTags[1] . ti_Tag = GA_Immediate;
MoreTags[1] . ti_Data = TRUE;
MoreTags[2] . ti_Tag = TAG_MORE;
MoreTags[2] . ti_Data = (ULONG)TagList;
if(!FindTagItem(GTIN_EditHook,TagList))
TagList = MoreTags;
else
TagList = MoreTags + 1;
break;
case FILE_KIND:
case FOLDER_KIND:
case SCREEN_KIND:
New -> ng_GadgetText = "";
break;
}
/* Restore default object width if necessary. */
if(SaveWidth)
SZ_CurrentWidth = Width;
if(!DropTop)
{
/* Are we to leave the top edge untouched? */
if(SetBelow)
{
/* Extend window height if necessary. */
if(Top + Height + AddHeight > SZ_WindowHeight)
SZ_WindowHeight = Top + Height + AddHeight;
}
else
{
SZ_CurrentTop = Top;
if(MoveDown)
{
/* Move down to next object. */
SZ_CurrentTop = SZ_CurrentTop + Height + AddHeight;
/* Extend window height if necessary. */
if(SZ_CurrentTop > SZ_WindowHeight)
SZ_WindowHeight = SZ_CurrentTop;
}
else
{
/* Extend window height if necessary. */
if(SZ_CurrentTop + Height + AddHeight > SZ_WindowHeight)
SZ_WindowHeight = SZ_CurrentTop + Height + AddHeight;
SZ_MaxWidth = 0;
}
}
}
if(!DropLeft)
{
/* Update maximum object width. */
if(Width > SZ_MaxWidth)
SZ_MaxWidth = Width;
/* Extend window width if necessary. */
if(Left + SZ_MaxWidth + InterWidth > SZ_WindowWidth)
SZ_WindowWidth = Left + SZ_MaxWidth + InterWidth;
/* Are we to leave the left edge untouched? */
if(!SetLeft)
SZ_CurrentLeft = Left;
}
/* Remember last object position and size. */
SZ_LastLeft = New -> ng_LeftEdge;
SZ_LastWidth = New -> ng_Width;
SZ_LastHeight = New -> ng_Height;
if(New -> ng_Flags & PLACETEXT_ABOVE)
SZ_LastTop = New -> ng_TopEdge - (INTERHEIGHT + SZ_TextFont -> tf_YSize);
else
SZ_LastTop = New -> ng_TopEdge;
}
}
/* Now for keystroke activation... */
switch(Kind)
{
case STRING_KIND:
case INTEGER_KIND:
case BUTTON_KIND:
case CHECKBOX_KIND:
case CYCLE_KIND:
case LISTVIEW_KIND:
case MX_KIND:
case PALETTE_KIND:
case SCROLLER_KIND:
case SLIDER_KIND:
case PASSWORD_KIND:
/* Do we have a gadget label? */
if(New -> ng_GadgetText)
{
/* Look for the underscore
* character...
*/
for(i = 0 ; i < strlen(New -> ng_GadgetText) ; i++)
{
if(New -> ng_GadgetText[i] == '_')
{
/* Is it a printable character? */
if((WORD)(New -> ng_GadgetText[i + 1]) > ' ')
{
/* Create information buffer. */
if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
{
STATIC struct TagItem EvenMoreTags[2];
EvenMoreTags[0] . ti_Tag = GT_Underscore;
EvenMoreTags[0] . ti_Data = '_';
EvenMoreTags[1] . ti_Tag = TAG_MORE;
EvenMoreTags[1] . ti_Data = (ULONG)TagList;
TagList = EvenMoreTags;
/* Set up the default data. */
Info -> PointBack = Info;
Info -> Kind = Kind;
Info -> Key = New -> ng_GadgetText[i + 1];
/* Add object-specific information. */
if(Info -> Kind == PALETTE_KIND)
{
Info -> Current = 1;
Info -> Max = 1;
}
if(Info -> Kind == LISTVIEW_KIND)
Info -> Current = ~0;
break;
}
}
}
}
}
break;
default:
break;
}
/* No GadgetInfo supplied yet? Does this object need any? */
if(!Info && (Kind == PASSWORD_KIND || Kind == FILE_KIND || Kind == FOLDER_KIND || Kind == SCREEN_KIND || Flags || NewGadgetTitle))
{
/* Allocate GadgetInfo. */
if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
{
Info -> PointBack = Info;
Info -> Kind = Kind;
}
}
/* Fill in object info if available. */
New -> ng_UserData = Info;
/* Fill in the new title if available. */
if(NewGadgetTitle)
New -> ng_GadgetText = NewGadgetTitle;
/* Did we create any object info? */
if(Info)
{
struct Node *Node;
struct List *List;
LONG Count;
STRPTR *Strings;
struct TagItem *NewTagList;
/* The following code takes care of object-specific
* characteristics, such as currently selected items,
* current value, minimum value, maximum value, etc.
* and places them in the gadget info.
*/
switch(Kind)
{
case CHECKBOX_KIND:
if(ThisTag = FindTagItem(GTCB_Checked,TagList))
Info -> Current = ThisTag -> ti_Data;
break;
case CYCLE_KIND:
if(ThisTag = FindTagItem(GTCY_Active,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTCY_Labels,TagList))
{
Count = 0;
if(Strings = (STRPTR *)ThisTag -> ti_Data)
{
while(Strings[Count])
Count++;
}
if(Count)
Info -> Max = Count - 1;
}
break;
case LISTVIEW_KIND:
if(ThisTag = FindTagItem(GTLV_Selected,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTLV_ReadOnly,TagList))
{
if(ThisTag -> ti_Data)
Info -> ReadOnly = TRUE;
}
if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
{
if(ThisTag -> ti_Data)
Info -> ReadOnly = FALSE;
}
if(ThisTag = FindTagItem(GTLV_Labels,TagList))
{
Count = 0;
if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
{
List = (struct List *)ThisTag -> ti_Data;
Node = List -> lh_Head;
while(Node -> ln_Succ)
{
Count++;
Node = Node -> ln_Succ;
}
}
if(Count)
Info -> Max = Count - 1;
}
break;
case MX_KIND:
if(ThisTag = FindTagItem(GTMX_Active,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTMX_Labels,TagList))
{
Count = 0;
if(Strings = (STRPTR *)ThisTag -> ti_Data)
{
while(Strings[Count])
Count++;
}
if(Count)
Info -> Max = Count - 1;
}
break;
case SCROLLER_KIND:
if(ThisTag = FindTagItem(GTSC_Top,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTSC_Total,TagList))
Info -> Max = ThisTag -> ti_Data;
break;
case SLIDER_KIND:
if(ThisTag = FindTagItem(GTSL_Level,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTSL_Min,TagList))
Info -> Min = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTSL_Max,TagList))
Info -> Max = ThisTag -> ti_Data;
break;
case PALETTE_KIND:
if(ThisTag = FindTagItem(GTPA_Color,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTPA_Depth,TagList))
Info -> Max = (1 << ((LONG)ThisTag -> ti_Data)) - 1;
break;
}
/* In order to avoid collisions with system software tags,
* we will clone the current tag item list and filter
* our private tags out before surrendering it to
* CreateGadget().
*/
if(NewTagList = CloneTagItems(TagList))
{
/* Remove the private tags. */
FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
/* Are we to create a custom button object? */
if(Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND)
{
BYTE Type;
/* Which kind of object are we to create? */
switch(Kind)
{
case FOLDER_KIND:
Type = BUTTONIMAGE_FOLDER;
break;
case FILE_KIND:
Type = BUTTONIMAGE_FILE;
break;
case SCREEN_KIND:
Type = BUTTONIMAGE_SCREEN;
break;
}
/* Create the images. */
if(Info -> Image = CreateButtonImages(Type,New -> ng_Width,New -> ng_Height,SZ_Screen,VisualInfo))
{
/* Create the object and attach the info to it. */
if(Result = OldCreateGadgetA(GENERIC_KIND,Previous,New,NewTagList))
{
Result -> GadgetType |= GTYP_BOOLGADGET;
Result -> GadgetRender = &Info -> Image[0];
Result -> SelectRender = &Info -> Image[1];
Result -> Flags |= GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
Result -> Activation |= GACT_RELVERIFY;
}
}
else
Result = NULL;
}
else
{
/* Are we to create a password entry string gadget? */
if(Kind == PASSWORD_KIND)
{
LONG MaxChars = 0;
/* Determine number of characters
* the gadget is to hold.
*/
if(ThisTag = FindTagItem(GTST_MaxChars,NewTagList))
MaxChars = ThisTag -> ti_Data;
/* Any size set? */
if(MaxChars)
{
/* Allocate the auxilary buffers. */
if(Info -> Original = (STRPTR)AllocVec((MaxChars + 2) * 2,MEMF_PUBLIC|MEMF_CLEAR))
{
/* Set up the text entry buffer. */
Info -> Buffer = Info -> Original + (MaxChars + 2);
/* If available find the original
* string this gadget is to be
* preset with.
*/
if(ThisTag = FindTagItem(GTST_String,NewTagList))
{
LONG Len;
/* Remember the original data. */
strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
/* Determine length of the original text. */
Len = strlen(Info -> Original);
/* Provide fake input. */
memset(SharedBuffer,'*',Len);
SharedBuffer[Len] = 0;
/* This is our own private tag item
* list, so why bother.
*/
ThisTag -> ti_Data = (ULONG)SharedBuffer;
}
Result = OldCreateGadgetA(STRING_KIND,Previous,New,NewTagList);
}
else
Result = NULL;
}
else
Result = NULL;
}
else
{
/* Create the object and attach the info to it. */
Result = OldCreateGadgetA(Kind,Previous,New,NewTagList);
}
}
/* Successful? */
if(Result)
{
/* Fill in the data. */
Info -> Gadget = Result;
Info -> Flags = Flags;
Info -> Title = NewGadgetTitle;
}
else
{
/* Free the images. */
if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND || Info -> Kind == SCREEN_KIND))
{
WORD i;
for(i = 0 ; i < 2 ; i++)
FreeVec(Info -> Image[i] . ImageData);
FreeVec(Info -> Image);
}
/* Free the password gadget buffers. */
if(Info -> Original && Info -> Kind == PASSWORD_KIND)
FreeVec(Info -> Original);
/* Free alternative gadget label. */
if(NewGadgetTitle)
FreeVec(NewGadgetTitle);
/* Free the info buffer itself. */
FreeMem(Info,sizeof(struct GadgetSupportInfo));
}
/* Free the private tag item list. */
FreeTagItems(NewTagList);
}
else
{
/* Free alternative gadget label. */
if(NewGadgetTitle)
FreeVec(NewGadgetTitle);
/* Free the info buffer itself. */
FreeMem(Info,sizeof(struct GadgetSupportInfo));
Result = NULL;
}
}
else
{
/* No private objects, please. */
if(Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == SCREEN_KIND || Kind == PASSWORD_KIND)
Result = NULL;
else
{
struct TagItem *NewTagList;
/* Copy the tag item list. */
if(NewTagList = CloneTagItems(TagList))
{
/* Filter out the private tags if any. */
FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
/* Create the object. */
Result = OldCreateGadgetA(Kind,Previous,New,TagList);
/* Free the private tag item list. */
FreeTagItems(NewTagList);
}
}
}
va_end(VarArgs);
/* Patch in the GACT_IMMEDIATE flag for string gadget objects under
* v37. Although this does not look very clean it is temporarily
* permitted for this single release.
*/
if(Result && GadToolsBase -> lib_Version == 37 && (Kind == STRING_KIND || Kind == INTEGER_KIND || Kind == PASSWORD_KIND))
Result -> Activation |= GACT_IMMEDIATE;
return(Result);
}
/* GT_SetGadgetAttrs():
*
* A frontend to the original routine.
*/
VOID
GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...)
{
va_list VarArgs;
struct TagItem *TagList,
*ThisTag;
struct GadgetSupportInfo *Info;
/* Get the tag item list. */
va_start(VarArgs,Requester);
TagList = (struct TagItem *)VarArgs;
/* Does the object in question have an info structure attached? */
if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
{
/* Does the data look sensible? */
if(Info -> PointBack == Info && Info -> Gadget == Gadget)
{
struct Node *Node;
struct List *List;
LONG Count;
STRPTR *Strings;
/* Update object-specific information. */
switch(Info -> Kind)
{
case CHECKBOX_KIND:
if(ThisTag = FindTagItem(GTCB_Checked,TagList))
Info -> Current = ThisTag -> ti_Data;
break;
case CYCLE_KIND:
if(ThisTag = FindTagItem(GTCY_Active,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTCY_Labels,TagList))
{
Count = 0;
if(Strings = (STRPTR *)ThisTag -> ti_Data)
{
while(Strings[Count])
Count++;
}
if(Count)
Info -> Max = Count - 1;
else
Info -> Max = 0;
}
break;
case LISTVIEW_KIND:
if(ThisTag = FindTagItem(GTLV_Selected,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTLV_Labels,TagList))
{
Count = 0;
if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
{
List = (struct List *)ThisTag -> ti_Data;
Node = List -> lh_Head;
while(Node -> ln_Succ)
{
Count++;
Node = Node -> ln_Succ;
}
}
if(Count)
Info -> Max = Count - 1;
else
Info -> Max = 0;
}
break;
case PALETTE_KIND:
if(ThisTag = FindTagItem(GTPA_Color,TagList))
Info -> Current = ThisTag -> ti_Data;
break;
case MX_KIND:
if(ThisTag = FindTagItem(GTMX_Active,TagList))
Info -> Current = ThisTag -> ti_Data;
break;
case SCROLLER_KIND:
if(ThisTag = FindTagItem(GTSC_Top,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTSC_Total,TagList))
Info -> Max = ThisTag -> ti_Data;
break;
case SLIDER_KIND:
if(ThisTag = FindTagItem(GTSL_Level,TagList))
Info -> Current = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(GTSL_Min,TagList))
Info -> Min = ThisTag -> ti_Data;
break;
case PASSWORD_KIND:
if(FindTagItem(GTST_String,TagList))
{
struct TagItem *NewTagList;
if(NewTagList = CloneTagItems(TagList))
{
LONG Len;
ThisTag = FindTagItem(GTST_String,NewTagList);
Forbid();
strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
Len = strlen(Info -> Buffer);
memset(SharedBuffer,'*',Len);
SharedBuffer[Len] = 0;
ThisTag -> ti_Data = (ULONG)SharedBuffer;
OldGT_SetGadgetAttrsA(Gadget,Window,Requester,NewTagList);
FreeTagItems(NewTagList);
Permit();
}
va_end(VarArgs);
return;
}
break;
}
}
}
/* Call the original routine. */
OldGT_SetGadgetAttrsA(Gadget,Window,Requester,TagList);
va_end(VarArgs);
}
/* FreeGadgets(struct Gadget *GadgetList):
*
* A frontend to the original routine.
*/
VOID
FreeGadgets(struct Gadget *GadgetList)
{
struct Gadget *Gadget = GadgetList;
struct GadgetSupportInfo *Info;
/* Run down the gadget list. */
while(Gadget)
{
/* Is this the previously active string gadget? */
if(Gadget == ActiveGadget)
ActiveGadget = NULL;
/* Does it have an info structure attached?*/
if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
{
/* Does the data make sense? */
if(Info -> PointBack == Info && Info -> Gadget == Gadget)
{
if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND || Info -> Kind == SCREEN_KIND))
{
WORD i;
for(i = 0 ; i < 2 ; i++)
FreeVec(Info -> Image[i] . ImageData);
FreeVec(Info -> Image);
}
if(Info -> Original && Info -> Kind == PASSWORD_KIND)
FreeVec(Info -> Original);
if(Info -> Title)
FreeVec(Info -> Title);
FreeMem(Info,sizeof(struct GadgetSupportInfo));
}
}
/* Skip to next object. */
Gadget = Gadget -> NextGadget;
}
OldFreeGadgets(GadgetList);
}
/* GT_ReplyIMsg(struct IntuiMessage *Message):
*
* A frontend to the original routine.
*/
VOID
GT_ReplyIMsg(struct IntuiMessage *Message)
{
/* Is this really a message? */
if(Message)
{
/* The following input event classes are likely to
* affect a gadtools object.
*/
if(Message -> Class == IDCMP_GADGETUP || Message -> Class == IDCMP_GADGETDOWN || Message -> Class == IDCMP_MOUSEMOVE)
{
struct Gadget *Gadget;
/* Take a look at the item attached. */
if(Gadget = (struct Gadget *)Message -> IAddress)
{
struct GadgetSupportInfo *Info = Gadget -> UserData;
/* If it's really a gadget, does it
* have an info structure attached?
*/
if(Info)
{
/* Does the data make sense? */
if(Info -> PointBack == Info && Info -> Gadget == Gadget)
{
LONG Value = (WORD)Message -> Code;
/* Update the object information. */
switch(Info -> Kind)
{
case CHECKBOX_KIND:
if(Gadget -> Flags & GFLG_SELECTED)
Info -> Current = TRUE;
else
Info -> Current = FALSE;
break;
case CYCLE_KIND:
Info -> Current = Message -> Code;
break;
case LISTVIEW_KIND:
Info -> Current = Message -> Code;
break;
case MX_KIND:
Info -> Current = Message -> Code;
break;
case SCROLLER_KIND:
Info -> Current = Message -> Code;
break;
case SLIDER_KIND:
if(Info -> Min >= 0 && Value < 0)
Info -> Current = Message -> Code;
else
Info -> Current = Value;
break;
case PALETTE_KIND:
Info -> Current = Message -> Code;
break;
default:
break;
}
}
}
}
}
}
/* Reply the message correctly. */
OldGT_ReplyIMsg(Message);
}
/* KeySelect():
*
* Handles gadget keystroke activation.
*/
VOID
KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code)
{
if(*IClass == IDCMP_VANILLAKEY)
{
/* If an escape code comes in and the window does in
* fact have a close gadget, return a close window
* event.
*/
if(Key == '\033' && (Window -> Flags & WFLG_CLOSEGADGET))
*IClass = IDCMP_CLOSEWINDOW;
else
{
struct GadgetSupportInfo *Info;
WORD i;
BYTE Forward,
GotIt = FALSE;
/* Run down all the gadgets. */
for(i = 0 ; !GotIt && i <= Last ; i++)
{
/* Is there a gadget? */
if(GadgetList[i])
{
/* Is this gadget enabled? */
if(!(GadgetList[i] -> Flags & GFLG_DISABLED))
{
/* Does it have an info structure attached? */
if(Info = GadgetList[i] -> UserData)
{
/* Does it make sense? */
if(Info -> PointBack == Info && Info -> Gadget == GadgetList[i])
{
/* Do the keys match? */
if(ToUpper(Info -> Key) == ToUpper(Key))
{
/* Are we cycle forward
* or backwards?
*/
if(ToUpper(Info -> Key) == Key)
Forward = FALSE;
else
Forward = TRUE;
/* Update the object information. */
switch(Info -> Kind)
{
case PASSWORD_KIND:
case STRING_KIND:
case INTEGER_KIND:
ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
*IClass = IDCMP_GADGETDOWN;
*Code = 0;
*Gadget = GadgetList[i];
GotIt = TRUE;
break;
case BUTTON_KIND:
*IClass = IDCMP_GADGETUP;
*Code = 0;
*Gadget = GadgetList[i];
GotIt = TRUE;
break;
case CHECKBOX_KIND:
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTCB_Checked, Info -> Current ? FALSE : TRUE,
TAG_DONE);
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
GotIt = TRUE;
break;
case CYCLE_KIND:
if(Forward)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTCY_Active, (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
TAG_DONE);
}
else
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTCY_Active, Info -> Current ? Info -> Current - 1 : Info -> Max,
TAG_DONE);
}
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
GotIt = TRUE;
break;
case LISTVIEW_KIND:
if(Forward)
{
if(Info -> Current == ~0)
Info -> Current = -1;
if(Info -> Current < Info -> Max)
{
if(Info -> ReadOnly)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTLV_Top, Info -> Current + 1,
GTLV_MakeVisible, Info -> Current + 1,
TAG_DONE);
}
else
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTLV_Selected, Info -> Current + 1,
GTLV_Top, Info -> Current + 1,
GTLV_MakeVisible, Info -> Current + 1,
TAG_DONE);
}
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
else
{
if(Info -> Current == ~0)
Info -> Current = Info -> Max + 1;
if(Info -> Current > Info -> Min)
{
if(Info -> ReadOnly)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTLV_Top, Info -> Current - 1,
GTLV_MakeVisible, Info -> Current - 1,
TAG_DONE);
}
else
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTLV_Selected, Info -> Current - 1,
GTLV_Top, Info -> Current - 1,
GTLV_MakeVisible, Info -> Current - 1,
TAG_DONE);
}
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
GotIt = TRUE;
break;
case MX_KIND:
if(Forward)
{
if(Info -> Current < Info -> Max)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTMX_Active, *Code = Info -> Current + 1,
TAG_DONE);
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
else
{
if(Info -> Current > Info -> Min)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTMX_Active, *Code = Info -> Current - 1,
TAG_DONE);
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
GotIt = TRUE;
break;
case PALETTE_KIND:
if(Forward)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTPA_Color, (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
TAG_DONE);
}
else
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTPA_Color, Info -> Current ? Info -> Current - 1 : Info -> Max,
TAG_DONE);
}
*IClass = IDCMP_GADGETUP;
*Code = Info -> Current;
*Gadget = GadgetList[i];
GotIt = TRUE;
break;
case SCROLLER_KIND:
if(Forward)
{
if(Info -> Current < Info -> Max)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTSC_Top, Info -> Current + 1,
TAG_DONE);
*IClass = IDCMP_MOUSEMOVE;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
else
{
if(Info -> Current > Info -> Min)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTSC_Top, Info -> Current - 1,
TAG_DONE);
*IClass = IDCMP_MOUSEMOVE;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
GotIt = TRUE;
break;
case SLIDER_KIND:
if(Forward)
{
if(Info -> Current < Info -> Max)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTSL_Level, Info -> Current + 1,
TAG_DONE);
*IClass = IDCMP_MOUSEMOVE;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
else
{
if(Info -> Current > Info -> Min)
{
GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
GTSL_Level, Info -> Current - 1,
TAG_DONE);
*IClass = IDCMP_MOUSEMOVE;
*Code = Info -> Current;
*Gadget = GadgetList[i];
}
}
GotIt = TRUE;
break;
}
}
}
}
}
}
}
/* If no matching object was found, take a closer look at the types. */
if(!GotIt)
{
for(i = 0 ; i <= Last ; i++)
{
/* If it's a string object, activate it. */
if(GadgetList[i])
{
if(!(GadgetList[i] -> Flags & GFLG_DISABLED) && (GadgetList[i] -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
{
ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
*IClass = IDCMP_GADGETDOWN;
*Code = 0;
*Gadget = GadgetList[i];
break;
}
}
}
}
}
}
/* Conjure up the AmigaGuide help window. */
if(*IClass == IDCMP_RAWKEY && *Code == 95)
GuideSetup();
}
/* SZ_ResetMaxWidth():
*
* Reset maximum object width and return current maximum width.
*/
LONG
SZ_ResetMaxWidth()
{
LONG Width = SZ_WidthMax;
SZ_WidthMax = 0;
return(Width);
}
/* SZ_UpdateMaxWidth():
*
* Update current maximum object width.
*/
VOID __regargs
SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
{
LONG Width = SZ_Width(Type,Title,Chars,Choices);
if(Width > SZ_WidthMax)
SZ_WidthMax = Width;
}
/* SZ_GetWindowWidth():
*
* Get the current window width.
*/
LONG
SZ_GetWindowWidth()
{
return(SZ_WindowWidth);
}
/* SZ_GetWindowHeight():
*
* Get the current window height.
*/
LONG
SZ_GetWindowHeight()
{
return(SZ_WindowHeight + SZ_Screen -> WBorBottom);
}
/* SZ_GetLeftEdge():
*
* Get the current object left edge.
*/
LONG
SZ_GetLeftEdge()
{
return(SZ_CurrentLeft);
}
/* SZ_GetTopEdge():
*
* Get the current object top edge.
*/
LONG
SZ_GetTopEdge()
{
return(SZ_CurrentTop);
}
/* SZ_SetTopEdge(LONG Top):
*
* Set the current object top edge.
*/
VOID __regargs
SZ_SetTopEdge(LONG Top)
{
SZ_CurrentTop = Top;
}
/* SZ_SetLeftEdge(LONG Left):
*
* Set the current object left edge.
*/
VOID __regargs
SZ_SetLeftEdge(LONG Left)
{
SZ_CurrentLeft = Left;
}
/* SZ_SetAbsoluteTop(LONG Top):
*
* Set new inner window top edge.
*/
VOID __regargs
SZ_SetAbsoluteTop(LONG Top)
{
SZ_Top = Top;
}
/* SZ_SetAbsoluteLeft(LONG Left):
*
* Set new inner window left edge.
*/
VOID __regargs
SZ_SetAbsoluteLeft(LONG Left)
{
SZ_Left = Left;
}
/* SZ_SetWidth(LONG Width):
*
* Set current object width.
*/
VOID __regargs
SZ_SetWidth(LONG Width)
{
SZ_CurrentWidth = Width;
}
VOID
SZ_InitWidth()
{
SZ_WindowWidth = SZ_Left + SZ_CurrentWidth + InterWidth;
}
/* SZ_GetDimension(LONG *Width,LONG *Height):
*
* Get current window dimensions.
*/
VOID __regargs
SZ_GetDimension(LONG *Width,LONG *Height)
{
*Width = SZ_WindowWidth;
*Height = SZ_WindowHeight + SZ_Screen -> WBorBottom;
}
/* SZ_GetChecked(struct Gadget *Gadget):
*
* Return whether a checkbox gadget is checked or not.
*/
BYTE __regargs
SZ_GetChecked(struct Gadget *Gadget)
{
if(Gadget -> Flags & GFLG_SELECTED)
return((BYTE)TRUE);
else
return((BYTE)FALSE);
}
/* SZ_GetInteger(struct Gadget *Gadget):
*
* Return the current settings of an integer gadget.
*/
LONG __regargs
SZ_GetInteger(struct Gadget *Gadget)
{
if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> LongInt);
else
return(0);
}
/* SZ_GetString(struct Gadget *Gadget):
*
* Returns the contents of a string gadet.
*/
STRPTR __regargs
SZ_GetString(struct Gadget *Gadget)
{
struct GadgetSupportInfo *Info;
/* Does the object in question have an info structure attached? */
if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
{
/* Does the data look sensible? */
if(Info -> PointBack == Info && Info -> Gadget == Gadget)
{
if(Info -> Kind == PASSWORD_KIND)
return(Info -> Buffer);
}
}
if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> Buffer);
else
return("");
}
/* SZ_TextWidth(STRPTR String):
*
* Determine string width in pixels.
*/
LONG __regargs
SZ_TextWidth(STRPTR String)
{
UBYTE TempString[256];
WORD i,j;
BYTE LastSpace = FALSE;
for(i = j = 0 ; String[i] ; i++)
{
if(String[i] == ' ')
LastSpace = TRUE;
else
LastSpace = FALSE;
if(String[i] != '_')
TempString[j++] = String[i];
}
if(LastSpace)
{
TempString[j] = 0;
String = NewTitle(TempString,0,NULL,FALSE);
j = strlen(String);
return(TextLength(SZ_RPort,String,j));
}
else
return(TextLength(SZ_RPort,TempString,j));
}
/* SZ_AddLeftOffset(LONG Offset):
*
* Update current object left offset.
*/
VOID __regargs
SZ_AddLeftOffset(LONG Offset)
{
SZ_CurrentLeft += Offset;
}
/* SZ_LeftOffsetN(LONG DataArray,...):
*
* Determine the maximum length of a number of
* gadget labels (first, second, third item, -1 terminates
* the array).
*/
LONG __stdargs
SZ_LeftOffsetN(LONG DataArray,...)
{
extern STRPTR __regargs LocaleString(LONG ID);
LONG *Data = &DataArray,
Len,
Max = 0;
while(*Data != -1)
{
if((Len = SZ_TextWidth(LocaleString(*Data++))) > Max)
Max = Len;
}
return(Max + INTERWIDTH);
}
/* SZ_LeftOffsetDelta(LONG From,LONG To):
*
* Determine the maximum length of a number of
* gadget labels (given as first and last gadget).
*/
LONG __regargs
SZ_LeftOffsetDelta(LONG From,LONG To)
{
extern STRPTR __regargs LocaleString(LONG ID);
LONG i,
Len,
Max = 0;
for(i = From ; i <= To ; i++)
{
if((Len = SZ_TextWidth(LocaleString(i))) > Max)
Max = Len;
}
return(Max + INTERWIDTH);
}
/* SZ_SizeCleanup():
*
* Free data allocated by SZ_SizeSetup().
*/
VOID
SZ_SizeCleanup()
{
if(SZ_TextFont)
{
CloseFont(SZ_TextFont);
SZ_TextFont = NULL;
}
if(SZ_RPort)
{
FreeVec(SZ_RPort);
SZ_RPort = NULL;
}
}
/* SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title):
*
* Perform setups for gadget creation.
*/
BYTE __regargs
SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title)
{
struct DrawInfo *DrawInfo;
SZ_SizeCleanup();
if(DrawInfo = GetScreenDrawInfo(Screen))
{
SZ_TextPen = DrawInfo -> dri_Pens[TEXTPEN];
FreeScreenDrawInfo(Screen,DrawInfo);
}
SZ_Screen = Screen;
if(SZ_RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY | MEMF_CLEAR))
{
InitRastPort(SZ_RPort);
if(!TextAttr)
TextAttr = Screen -> Font;
if(SZ_TextFont = (struct TextFont *)OpenDiskFont(TextAttr))
{
UWORD i,Width;
UBYTE Char;
InterWidth = INTERWIDTH;
if(SZ_TextFont -> tf_YSize <= 8)
InterHeight = 1;
else
InterHeight = SZ_TextFont -> tf_YSize / 4;
SetFont(SZ_RPort,SZ_TextFont);
SZ_AverageGlyphWidth = 0;
SZ_MaxGlyphWidth = 0;
SZ_MaxNumericWidth = 0;
for(i = 0 ; i < 256 ; i++)
{
Char = i;
Width = TextLength(SZ_RPort,&Char,1);
if(Width > SZ_MaxGlyphWidth)
SZ_MaxGlyphWidth = Width;
SZ_AverageGlyphWidth += Width;
}
SZ_AverageGlyphWidth /= 256;
for(i = '0' ; i <= '0' ; i++)
{
Char = i;
if((Width = TextLength(SZ_RPort,&Char,1)) > SZ_MaxNumericWidth)
SZ_MaxNumericWidth = Width;
}
if((Width = TextLength(SZ_RPort," ",1)) > SZ_MaxNumericWidth)
SZ_MaxNumericWidth = Width;
if((Width = TextLength(SZ_RPort,",",1)) > SZ_MaxNumericWidth)
SZ_MaxNumericWidth = Width;
if((Width = TextLength(SZ_RPort,".",1)) > SZ_MaxNumericWidth)
SZ_MaxNumericWidth = Width;
if(SZ_AverageGlyphWidth > SZ_MaxNumericWidth)
SZ_MaxNumericWidth = SZ_AverageGlyphWidth;
if(Title)
SZ_Top = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + InterHeight;
else
SZ_Top = Screen -> WBorTop + InterHeight;
SZ_Left = InterWidth;
SZ_CurrentLeft = InterWidth;
SZ_CurrentTop = SZ_Top;
SZ_WindowWidth = 0;
SZ_WindowHeight = 0;
SZ_CurrentWidth = 0;
SZ_MaxWidth = 0;
return(TRUE);
}
}
SZ_SizeCleanup();
return(FALSE);
}
/* SZ_GetNumericLen(STRPTR String):
*
* Get the string pixel width, measured using the maximum
* numeric glyph width.
*/
ULONG __regargs
SZ_GetNumericLen(STRPTR String)
{
return(strlen(String) * SZ_MaxNumericWidth);
}
/* SZ_GetGlyphLen(STRPTR String):
*
* Get the string pixel width, measured using the maximum
* glyph width.
*/
ULONG __regargs
SZ_GetGlyphLen(STRPTR String)
{
return(strlen(String) * SZ_MaxGlyphWidth);
}
/* SZ_GetLen(STRPTR String):
*
* Get the string pixel width, measured using the average
* glyph width.
*/
ULONG __regargs
SZ_GetLen(STRPTR String)
{
return(strlen(String) * SZ_AverageGlyphWidth);
}
/* SZ_Height(UBYTE Type,LONG Lines,BYTE Display):
*
* Determine the height of an object.
*/
LONG __regargs
SZ_Height(UBYTE Type,LONG Lines,BYTE Display)
{
LONG Height = 0;
switch(Type)
{
case LISTVIEW_KIND:
Height = 4 + Lines * SZ_TextFont -> tf_YSize + 4;
if(Display == SZLV_Display)
Height += 2 + SZ_TextFont -> tf_YSize + 2;
if(Display == SZLV_String)
Height += 3 + SZ_TextFont -> tf_YSize + 3;
break;
case FILE_KIND:
case FOLDER_KIND:
case SCREEN_KIND:
if(SZ_TextFont -> tf_YSize < 6)
Height = 12;
else
Height = 3 + SZ_TextFont -> tf_YSize + 3;
break;
case PASSWORD_KIND:
case INTEGER_KIND:
case STRING_KIND:
Height = 3 + SZ_TextFont -> tf_YSize + 3;
break;
case CYCLE_KIND:
case TEXT_KIND:
case BUTTON_KIND:
Height = 2 + SZ_TextFont -> tf_YSize + 2;
break;
case CHECKBOX_KIND:
if(SZ_TextFont -> tf_YSize < 11)
Height = 11;
else
Height = SZ_TextFont -> tf_YSize;
break;
case SLIDER_KIND:
Height = 1 + SZ_TextFont -> tf_YSize + 1;
break;
case MX_KIND:
Height = Lines * (SZ_TextFont -> tf_YSize + 1) - 1;
break;
case PALETTE_KIND:
Height = 2 * SZ_TextFont -> tf_YSize;
break;
}
return(Height);
}
/* SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices):
*
* Determine the width of an object.
*/
LONG __regargs
SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
{
LONG Width = 0,
Len,Max = 0,i;
switch(Type)
{
case LISTVIEW_KIND:
Width = (4 + Chars * SZ_AverageGlyphWidth + 4) + (2 + 2 * SZ_AverageGlyphWidth + 2) + 4; /* KLUDGE + 4 */
break;
case TEXT_KIND:
case BUTTON_KIND:
if(Title)
Width = 6 + SZ_TextWidth(Title) + 6;
else
Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
break;
case FILE_KIND:
case FOLDER_KIND:
case SCREEN_KIND:
if(SZ_AverageGlyphWidth <= 10)
Width = 20;
else
Width = 2 * SZ_AverageGlyphWidth;
if(Chars)
Width = 6 + Chars * SZ_AverageGlyphWidth + 6 - (2 + Width);
break;
case PASSWORD_KIND:
case SLIDER_KIND:
case STRING_KIND:
case INTEGER_KIND:
Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
break;
case CHECKBOX_KIND:
if(SZ_AverageGlyphWidth < 13)
Width = 26;
else
Width = 2 * SZ_AverageGlyphWidth;
break;
case CYCLE_KIND:
if(Choices)
{
for(i = 0 ; Choices[i] ; i++)
{
if((Len = TextLength(SZ_RPort,Choices[i],strlen(Choices[i]))) > Max)
Max = Len;
}
Width = 24 + Max + 4;
}
else
Width = 24 + Chars * SZ_AverageGlyphWidth + 4;
break;
case MX_KIND:
if(SZ_AverageGlyphWidth < 8)
Width = 17;
else
Width = 2 * SZ_AverageGlyphWidth;
break;
}
return(Width);
}
/* SZ_FreeBox(struct TextBox *Box):
*
* Free a text box.
*/
VOID __regargs
SZ_FreeBox(struct TextBox *Box)
{
if(Box)
{
if(Box -> Text)
{
LONG i;
for(i = 0 ; i < Box -> NumLines ; i++)
{
if(Box -> Text[i])
FreeVec(Box -> Text[i]);
}
FreeVec(Box -> Text);
}
if(Box -> Title)
FreeVec(Box -> Title);
FreeVec(Box);
}
}
/* SZ_FreeBoxes(struct TextBox *FirstBox):
*
* Free a number of text boxes.
*/
VOID __regargs
SZ_FreeBoxes(struct TextBox *FirstBox)
{
if(FirstBox)
{
struct TextBox *NextBox;
do
{
NextBox = FirstBox -> NextBox;
SZ_FreeBox(FirstBox);
FirstBox = NextBox;
}
while(FirstBox);
}
}
/* SZ_BoxWidth(LONG Chars):
*
* Determine the width of a text box.
*/
LONG __regargs
SZ_BoxWidth(LONG Chars)
{
return((LONG)(4 + SZ_AverageGlyphWidth * Chars + 4));
}
/* SZ_BoxHeight(LONG Lines):
*
* Determine the height of a text box.
*/
LONG __regargs
SZ_BoxHeight(LONG Lines)
{
return(2 + SZ_TextFont -> tf_YSize * Lines + 2);
}
/* SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen):
*
* Set the text box list title text rendering pens.
*/
VOID __regargs
SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen)
{
while(Box)
{
Box -> TitleFgPen = FgPen;
Box -> TitleBgPen = BgPen;
Box = Box -> NextBox;
}
}
/* SZ_CreateTextBox(struct TextBox **FirstBox,...):
*
* Create a text box, this routine works similar
* to the CreateGadget() frontend.
*/
struct TextBox * __stdargs
SZ_CreateTextBox(struct TextBox **FirstBox,...)
{
va_list VarArgs;
struct TagItem *TagList,
*ThisTag;
LONG Chars,Lines,
Width,
Height,
Left = SZ_CurrentLeft;
BYTE AutoWidth = FALSE,
MoveDown = TRUE,
SetLeft = FALSE,
SetBelow = FALSE;
struct TextBox *Box;
LONG i;
va_start(VarArgs,FirstBox);
TagList = (struct TagItem *)VarArgs;
if(ThisTag = FindTagItem(SZ_Lines,TagList))
Lines = (LONG)ThisTag -> ti_Data;
else
return(NULL);
Height = 2 + SZ_TextFont -> tf_YSize * Lines + 2;
if(ThisTag = FindTagItem(SZ_Chars,TagList))
Chars = (LONG)ThisTag -> ti_Data;
else
{
if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
AutoWidth = ThisTag -> ti_Data;
if(!AutoWidth)
return(NULL);
else
Chars = (SZ_CurrentWidth - 8) / SZ_AverageGlyphWidth;
}
if(!(Box = (struct TextBox *)AllocVec(sizeof(struct TextBox),MEMF_ANY | MEMF_CLEAR)))
return(NULL);
if(ThisTag = FindTagItem(SZ_SaveX,TagList))
SetLeft = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(SZ_SaveY,TagList))
SetBelow = ThisTag -> ti_Data;
if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
{
if(ThisTag -> ti_Data)
SZ_CurrentTop = SZ_WindowHeight;
}
if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
{
if(ThisTag -> ti_Data)
SZ_CurrentTop += InterHeight;
}
if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
{
if(ThisTag -> ti_Data)
{
SZ_CurrentTop = SZ_Top;
Left = Left + SZ_MaxWidth + InterWidth;
SZ_MaxWidth = 0;
}
}
if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
AutoWidth = ThisTag -> ti_Data;
if(!AutoWidth)
Width = SZ_BoxWidth(Chars);
else
Width = SZ_CurrentWidth;
if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
{
if(ThisTag -> ti_Data)
{
Left = SZ_Left;
MoveDown = FALSE;
}
}
if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
{
if(ThisTag -> ti_Data)
{
Left = SZ_WindowWidth - INTERWIDTH - Width;
MoveDown = FALSE;
}
}
if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
{
if(ThisTag -> ti_Data)
{
Left = (SZ_WindowWidth - Width) / 2;
MoveDown = FALSE;
}
}
if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
{
LONG Count = ThisTag -> ti_Data,Width = SZ_WindowWidth;
if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
{
Width -= ThisTag -> ti_Data - InterWidth;
SZ_GroupDelta = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
SZ_GroupX = Left = ThisTag -> ti_Data;
}
else
{
SZ_GroupDelta = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
SZ_GroupX = Left = SZ_Left;
}
MoveDown = FALSE;
}
else
{
if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
Left = ThisTag -> ti_Data;
}
if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
{
if(ThisTag -> ti_Data)
{
SZ_GroupX += SZ_GroupDelta;
Left = SZ_GroupX;
MoveDown = FALSE;
}
}
if(ThisTag = FindTagItem(SZ_UseTop,TagList))
SZ_CurrentTop = ThisTag -> ti_Data;
Box -> Left = Left;
Box -> Top = SZ_CurrentTop;
Box -> Width = Width;
Box -> Height = Height;
Box -> LineWidth = Chars * SZ_AverageGlyphWidth;
Box -> LineHeight = SZ_TextFont -> tf_YSize;
Box -> NumChars = Chars;
Box -> NumLines = Lines;
Box -> TitleFgPen = SZ_TextPen;
Box -> TitleBgPen = 0;
Box -> TextPen = SZ_TextPen;
if(!(Box -> Title = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
if(!(Box -> Text = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
for(i = 0 ; i < Lines ; i++)
{
if(!(Box -> Text[i] = (STRPTR)AllocVec(Chars + 1,MEMF_ANY | MEMF_CLEAR)))
{
SZ_FreeBox(Box);
return(NULL);
}
}
if(SetBelow)
MoveDown = FALSE;
if(MoveDown)
{
SZ_CurrentTop = SZ_CurrentTop + Height + InterHeight;
if(SZ_CurrentTop > SZ_WindowHeight)
SZ_WindowHeight = SZ_CurrentTop;
}
else
{
if(SZ_CurrentTop + Height + InterHeight > SZ_WindowHeight)
SZ_WindowHeight = SZ_CurrentTop + Height + InterHeight;
SZ_MaxWidth = 0;
}
if(Width > SZ_MaxWidth)
SZ_MaxWidth = Width;
if(Left + SZ_MaxWidth + INTERWIDTH > SZ_WindowWidth)
SZ_WindowWidth = Left + SZ_MaxWidth + INTERWIDTH;
if(!SetLeft)
SZ_CurrentLeft = Left;
if(!(*FirstBox))
*FirstBox = Box;
else
{
struct TextBox *CurrentBox = *FirstBox;
while(CurrentBox -> NextBox)
CurrentBox = CurrentBox -> NextBox;
CurrentBox -> NextBox = Box;
}
return(Box);
}
/* SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...):
*
* Set the titles displayed in a text box.
*/
VOID __stdargs
SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...)
{
if(Box)
{
STRPTR *Data = &Array;
LONG i = 0;
while(*Data != NULL)
{
if(i < Box -> NumLines)
Box -> Title[i++] = *Data;
Data++;
}
}
}
/* SZ_SetLine():
*
* Print a string into a text box, plain version.
*/
VOID __regargs
SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String)
{
BYTE FgPen = ReadAPen(RPort),
BgPen = ReadBPen(RPort),
DrMd = ReadDrMd(RPort);
struct TextFont *Font = RPort -> Font;
LONG Width,Len,
Left = Box -> Left + 4,
Top = Box -> Top + 2 + Line * Box -> LineHeight;
if(DrMd != JAM2)
SetDrMd(RPort,JAM2);
if(FgPen != Box -> TextPen)
SetAPen(RPort,Box -> TextPen);
if(BgPen != 0)
SetBPen(RPort,0);
if(Font != UserTextFont)
SetFont(RPort,UserTextFont);
if(Len = strlen(String))
{
if(Len > Box -> NumChars)
Len = Box -> NumChars;
while(Len > 0 && TextLength(RPort,String,Len) > Box -> LineWidth)
Len--;
if(Len)
{
Width = TextLength(RPort,String,Len);
Move(RPort,Left,Top + RPort -> Font -> tf_Baseline);
Text(RPort,String,Len);
}
else
Width = 0;
}
else
Width = 0;
if(Width != Box -> LineWidth)
{
if(FgPen != 0)
{
SetAPen(RPort,0);
RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
SetAPen(RPort,FgPen);
}
else
RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
}
if(DrMd != JAM2)
SetDrMd(RPort,DrMd);
if(String != Box -> Text[Line])
{
if(Len > 0)
memcpy(Box -> Text[Line],String,Len);
Box -> Text[Line][Len] = 0;
}
if(Font != UserTextFont)
SetFont(RPort,Font);
if(BgPen != 0)
SetBPen(RPort,BgPen);
SetAPen(RPort,FgPen);
}
/* SZ_PrintLine():
*
* Print a string into a text box, varargs version.
*/
VOID __stdargs
SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...)
{
extern VOID __stdargs VSPrintf(APTR,STRPTR,va_list);
va_list VarArgs;
UBYTE Buffer[256];
va_start(VarArgs,String);
VSPrintf(Buffer,String,VarArgs);
va_end(VarArgs);
SZ_SetLine(RPort,Box,Line,Buffer);
}
/* SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box):
*
* (Re-)Draw a text box.
*/
VOID __regargs
SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box)
{
if(Box)
{
LONG LineY,i,Len,FgPen = ReadAPen(RPort),BgPen = ReadBPen(RPort),DrMd = ReadDrMd(RPort);
struct TextFont *Font = RPort -> Font;
if(Font != UserTextFont)
SetFont(RPort,UserTextFont);
if(FgPen != 0)
{
SetAPen(RPort,0);
RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
SetAPen(RPort,FgPen);
}
else
RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
DrawBevelBox(RPort,Box -> Left,Box -> Top,Box -> Width,Box -> Height,
GT_VisualInfo, VisualInfo,
GTBB_Recessed, TRUE,
TAG_DONE);
LineY = Box -> Top + 2 + RPort -> Font -> tf_Baseline;
SetAPen(RPort,Box -> TitleFgPen);
SetBPen(RPort,Box -> TitleBgPen);
SetDrMd(RPort,JAM2);
for(i = 0 ; i < Box -> NumLines ; i++)
{
if(Len = strlen(Box -> Title[i]))
{
Move(RPort,Box -> Left - INTERWIDTH - TextLength(RPort,Box -> Title[i],Len),LineY);
Text(RPort,Box -> Title[i],Len);
}
LineY += Box -> LineHeight;
}
for(i = 0 ; i < Box -> NumLines ; i++)
SZ_PrintLine(RPort,Box,i,Box -> Text[i]);
SetAPen(RPort,FgPen);
SetBPen(RPort,BgPen);
SetDrMd(RPort,DrMd);
if(Font != UserTextFont)
SetFont(RPort,Font);
}
}
/* SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox):
*
* (Re-)Draw a number of text boxes.
*/
VOID __regargs
SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox)
{
do
SZ_DrawBox(RPort,FirstBox);
while(FirstBox = FirstBox -> NextBox);
}
/* SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top):
*
* Change the location of a text box.
*/
VOID __regargs
SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top)
{
Box -> Left += Left;
Box -> Top += Top;
}
/* SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
*
* Change the locations of a number of text boxes.
*/
VOID __regargs
SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
{
do
SZ_MoveBox(FirstBox,Left,Top);
while(FirstBox = FirstBox -> NextBox);
}
/* SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top):
*
* Set the location of a text box.
*/
VOID __regargs
SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top)
{
if(Left >= 0)
Box -> Left = Left;
if(Top >= 0)
Box -> Top = Top;
}
/* SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
*
* Set the locations of a number of text boxes.
*/
VOID __regargs
SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
{
do
SZ_SetBox(FirstBox,Left,Top);
while(FirstBox = FirstBox -> NextBox);
}
/* SZ_GetBoxInfo(struct TextBox *Box,LONG Type):
*
* Query information on a certain text box.
*/
LONG __regargs
SZ_GetBoxInfo(struct TextBox *Box,LONG Type)
{
switch(Type)
{
case BOX_LEFT:
return(Box -> Left);
case BOX_TOP:
return(Box -> Top);
case BOX_WIDTH:
return(Box -> Width);
case BOX_HEIGHT:
return(Box -> Height);
default:
return(0);
}
}